/**
 * This file is part of Lineage II Client Data Parser.
 * 
 * Lineage II Client Data Parser is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * Lineage II Client Data Parser is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with Lineage II Client Data Parser.  If not, see <http://www.gnu.org/licenses/>.
 */
package net.l2emuproject.parser;

import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

import net.l2emuproject.Launcher;
import net.l2emuproject.entity.Credit;
import net.l2emuproject.io.FileManager;
import net.l2emuproject.io.SafelyPackedFile;
import net.l2emuproject.parser.base.DefaultParser;
import net.l2emuproject.redist.UnsupportedException;

import javolution.text.TextBuilder;

/**
 * @author Savormix
 *
 */
public final class CreditParser extends DefaultParser
{
	private static final String[]	NEEDED_FILES	=
													{ Launcher.FILES[6] };

	private final List<Credit>		list;

	/**
	 * Creates a parser that parses starter class description data. Needed Files:
	 * <LI>ClassInfo-e</LI>
	 * @param spf File array
	 * @throws IllegalArgumentException Wrong file(s) 
	 */
	public CreditParser(SafelyPackedFile... spf) throws IllegalArgumentException
	{
		super(spf);
		list = new ArrayList<Credit>(80);
	}

	/** Creates a parser that validates files */
	public CreditParser()
	{
		super();
		list = null;
	}

	private final boolean parseCredits(int entryCnt, SafelyPackedFile spf)
	{
		if (!isValidator())
			log.info("Reading " + entryCnt + " entries from " + spf.getFileName());
		for (int i = 0; i < entryCnt; i++)
		{
			if (isValidator())
				return (spf.readInt() == 1 && !spf.readString().isEmpty());
			list.add(new Credit(spf.readInt(), spf.readString(), spf.readString(), spf.readInt(), spf.readInt()));
		}
		log.info("Finished reading " + spf.getFileName());
		return false;
	}

	/* (non-Javadoc)
	 * @see com.l2cdp.parser.base.IParser#getNeededFiles()
	 */
	@Override
	public String[] getNeededFiles()
	{
		return NEEDED_FILES;
	}

	/* (non-Javadoc)
	 * @see com.l2cdp.parser.base.IParser#getParseType()
	 */
	@Override
	public String getParseType()
	{
		return "credit";
	}

	/* (non-Javadoc)
	 * @see com.l2cdp.parser.base.IParser#readClientData()
	 */
	@Override
	public void readClientData() throws IllegalAccessException
	{
		if (isValidator())
			throw new IllegalAccessException(toString());
		parseCredits(entries[0], spf[0]);
	}

	/* (non-Javadoc)
	 * @see com.l2cdp.parser.base.IParser#selfAdvancedAnalysis()
	 */
	@Override
	public void selfAdvancedAnalysis() throws IllegalAccessException
	{
		if (isValidator())
			throw new IllegalAccessException(toString());
		for (Credit c : list)
		{
			if (ANALYZE_DETERMINISTIC)
				c.deterministicAnalysis();
			if (ANALYZE_EXPERIMENTAL)
				c.experimentalAnalysis();
		}
	}

	/* (non-Javadoc)
	 * @see com.l2cdp.parser.base.IParser#validate(com.l2cdp.io.SafelyPackedFile)
	 */
	@Override
	public boolean validate(SafelyPackedFile spf)
	{
		try
		{
			return parseCredits(spf.readInt(), spf);
		}
		catch (Exception e)
		{
			return false;
		}
	}

	/* (non-Javadoc)
	 * @see com.l2cdp.parser.base.IParser#writeServerData(int)
	 */
	@Override
	public void writeServerData(int chronicle) throws IllegalAccessException
	{
		if (isValidator())
			throw new IllegalAccessException(toString());
	}

	/* (non-Javadoc)
	 * @see com.l2cdp.parser.base.IParser#writeSimpleData(int)
	 */
	@Override
	public void writeSimpleData(int chronicle) throws IllegalAccessException
	{
		if (isValidator())
			throw new IllegalAccessException(toString());
		synchronized (finLock)
		{
			addThread();
		}
		new Thread(new AsyncWriterCreditsSim(chronicle), AsyncWriterCreditsSim.class.getName()).start();
	}

	protected class AsyncWriterCreditsSim implements Runnable
	{
		private final int	cID;

		protected AsyncWriterCreditsSim(int cID)
		{
			this.cID = cID;
		}

		/* (non-Javadoc)
		 * @see java.lang.Runnable#run()
		 */
		@Override
		public void run()
		{
			TextBuilder sb = TextBuilder.newInstance();
			try
			{
				Writer w = FileManager.getWriter(cID, "credits.properties", true);
				addGenInfo(cID, sb, COMMENT_PROP);
				for (Credit c : list)
				{
					sb.append(c.getId());
					sb.append(EQUAL);
					sb.append(c.getFile());
					sb.append(COMMA);
					sb.append(c.getTexture());
					sb.append(SEMICOLON);
					sb.append(c.getTime());
					sb.append(COMMA);
					sb.append(c.getAlign());
					sb.append(LINE_BREAK);
				}
				addGenInfo(-1, sb, COMMENT_PROP);
				w.write(sb.toString());
				w.close();
			}
			catch (UnsupportedException e)
			{
				log.fatal("Unsupported chronicle, will not write data!", e);
			}
			catch (IOException e)
			{
				log.error("Cannot write credits.properties!", e);
			}
			finally
			{
				TextBuilder.recycle(sb);
				synchronized (finLock)
				{
					remThread();
				}
			}
		}
	}
}
